/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.tchepannou.limbe.engine;

import com.tchepannou.limbe.Interceptor;
import com.tchepannou.limbe.Service;
import com.tchepannou.limbe.Util;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import javax.servlet.ServletContext;
import javax.xml.parsers.*;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Logger;

/**
 *
 * @author Herve Tchepannou
 */
public class EngineConfigurator
    extends DefaultHandler
{
    //-- Attributes
    private int INTERCEPTOR_ACTION = 1;
    private int INTERCEPTOR_MAIL = 2;
    private int INTERCEPTOR_JOB = 3;
    private int INTERCEPTOR_MESSAGE = 4;

    private static final Logger LOG = Logger.getLogger(EngineConfigurator.class.getName());
    private static final String PATH = "/WEB-INF/limbe.xml";

    private StringBuilder _value = new StringBuilder();
    private Engine _engine;
    private Attributes _attributes;
    private int _interceptorType;

    //-- Public method
    public void configure (Engine engine, ServletContext sc)
        throws ConfigurationException
    {
        LOG.info("Configuring the Engine");

        this._engine = engine;
        try
        {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser parser = factory.newSAXParser();
            InputStream in = sc.getResourceAsStream(PATH);

            LOG.info("Parsing " + PATH);
            parser.parse(in, this);
            LOG.info("Parsing completed");
        }
        catch (ParserConfigurationException e)
        {
            throw new ConfigurationException ( "Invalid configuration file", e);
        }
        catch (SAXException e)
        {
            throw new ConfigurationException ( "Configuration error", e);
        }
        catch (IOException e)
        {
            throw new ConfigurationException ( "Configuration error", e);
        }
        finally
        {
            _engine = null;
            _value = null;
            _attributes = null;
        }
    }


    //-- DefaultHandler overrides
    @Override
    public void startElement(String uri, String localName,String name, Attributes attributes)
    {
        _value.setLength(0);
        _attributes = attributes;

        if ("action-interceptors".equalsIgnoreCase (name) )
        {
            _interceptorType =INTERCEPTOR_ACTION;
        }
        else if ("job-interceptors".equalsIgnoreCase (name) )
        {
            _interceptorType = INTERCEPTOR_JOB;
        }
        else if ("mail-interceptors".equalsIgnoreCase (name) )
        {
            _interceptorType = INTERCEPTOR_MAIL;
        }
        else if ("message-interceptors".equalsIgnoreCase (name) )
        {
            _interceptorType = INTERCEPTOR_MESSAGE;
        }

    }

    @Override
    public void endElement(String uri, String localName, String name) throws SAXException
    {
        String value = _value.toString().trim();
        LOG.info(name + "="  + value);
        try
        {
            if ( "login-url".equalsIgnoreCase (name))
            {
                _engine.setLoginURL (value);
            }
            else if ( "base-package".equalsIgnoreCase (name))
            {
                _engine.setBasePackage (value);
            }
            else if ("util-class".equalsIgnoreCase (name))
            {
                Class<? extends Util> clazz = (Class<? extends Util>)Class.forName (value);
                _engine.setUtilClass (clazz);
            }
            else if ( "service".equalsIgnoreCase (name) )
            {
                String type = _attributes.getValue("type");
                Class typeClass = Class.forName (type);
                Service service = ( Service ) Class.forName(value).newInstance ();
                _engine.registerService (typeClass, service);
            }
            else if ("action-interceptors".equalsIgnoreCase (name) )
            {
                _interceptorType = -1;
            }
            else if ("job-interceptors".equalsIgnoreCase (name) )
            {
                _interceptorType = -1;
            }
            else if ("mail-interceptors".equalsIgnoreCase (name) )
            {
                _interceptorType = -1;
            }
            else if ("message-interceptors".equalsIgnoreCase (name) )
            {
                _interceptorType = -1;
            }
            else if ( "interceptor".equalsIgnoreCase (name) )
            {
                Interceptor interceptor = ( Interceptor ) Class.forName (value).newInstance ();
                if (_interceptorType == INTERCEPTOR_ACTION)
                {
                    _engine.registerActionInterceptor (interceptor);
                }
                else if (_interceptorType == INTERCEPTOR_MAIL)
                {
                    _engine.registerMailInterceptor(interceptor);
                }
//                if (_interceptorType == INTERCEPTOR_JOB)
//                {
//                    _engine.registerJobInterceptor(interceptor);
//                }
//                if (_interceptorType == INTERCEPTOR_MESSAGE)
//                {
//                    _engine.registerMessageInterceptor(interceptor);
//                }
            }
        }
        catch (ClassNotFoundException e)
        {
            throw new SAXException(name + "=" + value, e);
        }
        catch (InstantiationException e)
        {
            throw new SAXException(name + "=" + value, e);
        }
        catch (IllegalAccessException e)
        {
            throw new SAXException(name + "=" + value, e);
        }
    }

    @Override
    public void characters(char ch[], int start, int length) throws SAXException
    {
        _value.append(ch, start, length);
    }

    //-- Private
//    @SuppressWarnings("unchecked")
//    private void handle(Engine engine, Element elt)
//        throws ClassNotFoundException,
//               InstantiationException,
//               IllegalAccessException
//    {
//        String name = elt.getTagName();
//        String value = getTextValue(elt);
//        if ( "login-url".equalsIgnoreCase (name) )
//        {
//            engine.setLoginURL (value);
//        }
//        else if ( "base-package".equalsIgnoreCase (name) )
//        {
//            engine.setBasePackage (value);
//        }
//        else if ("util-class".equalsIgnoreCase (name))
//        {
//            Class<? extends Util> clazz = (Class<? extends Util>)Class.forName (value);
//            engine.setUtilClass (clazz);
//        }
//        else if ( "services".equalsIgnoreCase (name) )
//        {
//            configureServices (engine, elt);
//        }
//        else if ("action-interceptors".equalsIgnoreCase (name) )
//        {
//            configureActionInterceptors (engine, elt);
//        }
//        else if ("job-interceptors".equalsIgnoreCase (name) )
//        {
//            configureJobInterceptors (engine, elt);
//        }
//        else if ("mail-interceptors".equalsIgnoreCase (name) )
//        {
//            configureMailInterceptors (engine, elt);
//        }
//        else if ("message-interceptors".equalsIgnoreCase (name) )
//        {
//            configureMessageInterceptors (engine, elt);
//        }
//    }
//
//    @SuppressWarnings({"unchecked", "rawtypes"})
//    private void configureServices (Engine engine, Element root)
//        throws ClassNotFoundException,
//               InstantiationException,
//               IllegalAccessException
//    {
//        NodeList children = root.getChildNodes();
//        int count = children.getLength();
//        for ( int i=0 ; i<count ; i++ )
//        {
//            Node node = children.item(i);
//            if (node instanceof Element)
//            {
//                Element elt = ( Element ) node;
//                String name = elt.getTagName();
//                String value = getTextValue(elt);
//                if ( "service".equalsIgnoreCase (name) )
//                {
//                    String type = elt.getAttribute("type");
//                    Class typeClass = Class.forName (type);
//                    Service service = ( Service ) Class.forName(value).newInstance ();
//                    engine.registerService (typeClass, service);
//                }
//            }
//        }
//    }
//
//    private void configureActionInterceptors (Engine engine, Element root)
//        throws ClassNotFoundException,
//               InstantiationException,
//               IllegalAccessException
//    {
//        NodeList children = root.getChildNodes();
//        int count = children.getLength();
//        for ( int i=0 ; i<count ; i++ )
//        {
//            Node node = children.item(i);
//            if (node instanceof Element)
//            {
//                Element elt = ( Element ) node;
//                String name = elt.getTagName();
//                String value = getTextValue(elt);
//                if ( "interceptor".equalsIgnoreCase (name) )
//                {
//                    Interceptor interceptor = ( Interceptor ) Class.forName (value).newInstance ();
//                    engine.registerActionInterceptor (interceptor);
//                }
//            }
//        }
//    }
//
//    private void configureJobInterceptors (Engine engine, Element root)
//        throws ClassNotFoundException,
//               InstantiationException,
//               IllegalAccessException
//    {
//        NodeList children = root.getChildNodes();
//        int count = children.getLength();
//        for ( int i=0 ; i<count ; i++ )
//        {
//            Node node = children.item(i);
//            if (node instanceof Element)
//            {
//                Element elt = ( Element ) node;
//                String name = elt.getTagName();
//                String value = getTextValue(elt);
//                if ( "interceptor".equalsIgnoreCase (name) )
//                {
//                    Interceptor interceptor = ( Interceptor ) Class.forName (value).newInstance ();
//                    engine.registerJobInterceptor (interceptor);
//                }
//            }
//        }
//    }
//
//    private void configureMailInterceptors (Engine engine, Element root)
//        throws ClassNotFoundException,
//               InstantiationException,
//               IllegalAccessException
//    {
//        NodeList children = root.getChildNodes();
//        int count = children.getLength();
//        for ( int i=0 ; i<count ; i++ )
//        {
//            Node node = children.item(i);
//            if (node instanceof Element)
//            {
//                Element elt = ( Element ) node;
//                String name = elt.getTagName();
//                String value = getTextValue(elt);
//                if ( "interceptor".equalsIgnoreCase (name) )
//                {
//                    Interceptor interceptor = ( Interceptor ) Class.forName (value).newInstance ();
//                    engine.registerMailInterceptor (interceptor);
//                }
//            }
//        }
//    }
//
//    private void configureMessageInterceptors (Engine engine, Element root)
//        throws ClassNotFoundException,
//               InstantiationException,
//               IllegalAccessException
//    {
//        NodeList children = root.getChildNodes();
//        int count = children.getLength();
//        for ( int i=0 ; i<count ; i++ )
//        {
//            Node node = children.item(i);
//            if (node instanceof Element)
//            {
//                Element elt = ( Element ) node;
//                String name = elt.getTagName();
//                String value = getTextValue(elt);
//                if ( "interceptor".equalsIgnoreCase (name) )
//                {
//                    Interceptor interceptor = ( Interceptor ) Class.forName (value).newInstance ();
//                    engine.registerMessageInterceptor (interceptor);
//                }
//            }
//        }
//    }
//
//    private String getTextValue(Element ele)
//    {
//        Node node = ele.getFirstChild();
//        String txt = node != null ? node.getNodeValue() : null;
//        if (txt != null)
//        {
//            return txt.replaceAll("[\n\r]", "").trim();
//        }
//        return txt;
//    }
}
